Skip to content

Expose response headers in DocsService - #6191

Merged
ikhoon merged 38 commits into
line:mainfrom
hyunw9:add-Response-Header
Jun 23, 2025
Merged

Expose response headers in DocsService#6191
ikhoon merged 38 commits into
line:mainfrom
hyunw9:add-Response-Header

Conversation

@hyunw9

@hyunw9 hyunw9 commented Apr 5, 2025

Copy link
Copy Markdown
Contributor

Motivation

This PR addresses issue : #6187

“A response body is exposed in DocService but response headers are not. Since some APIs convey important information through response headers, exposing them in the debug console would be useful.”

Modifications

  • Modified the transport to return response headers along with the body when a request is made from the DocService’s debug console.

  • Updated the UI to display response headers in addition to the response body.

  • Changed the tooltip of the “Copy” button to say “Copy response body” for better clarity.

  • Improved API switching behavior in the debug UI

    • When the user navigates to another API and then returns to the previous one, the last debug response (body + headers) is now restored from the internal cache.
  • Screenshots

  1. Response Section
Before After
  1. Copy Response Button
Before After
  1. Improved API switching behavior

Before : When we click on another API in Docs, the existing response remains.
After : When we click on another API, the response value of the previous API remains on the previous page.

Before After

Result

  • Developers can now inspect both the response headers and response body for any API directly within the DocService debug console.

@hyunw9 hyunw9 changed the title feat : expose response headers in DocsService Expose response headers in DocsService Apr 5, 2025
@hyunw9 hyunw9 changed the title Expose response headers in DocsService Expose response headers in DocsService Apr 5, 2025
@trustin

trustin commented Apr 7, 2025

Copy link
Copy Markdown
Contributor

Would you mind share the screenshot or screencast that demonstrates the change for easier reviews?

@hyunw9

hyunw9 commented Apr 7, 2025

Copy link
Copy Markdown
Contributor Author

Would you mind share the screenshot or screencast that demonstrates the change for easier reviews?

Sure! I've just added a screenshot to make it easier to understand.

Comment thread docs-client/src/containers/MethodPage/DebugPage.tsx Outdated
@codecov

codecov Bot commented Apr 9, 2025

Copy link
Copy Markdown

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 74.60%. Comparing base (8150425) to head (add4c40).
Report is 61 commits behind head on main.

Additional details and impacted files
@@             Coverage Diff              @@
##               main    #6191      +/-   ##
============================================
+ Coverage     74.46%   74.60%   +0.14%     
- Complexity    22234    22470     +236     
============================================
  Files          1963     1972       +9     
  Lines         82437    82992     +555     
  Branches      10764    10798      +34     
============================================
+ Hits          61385    61915     +530     
- Misses        15918    15931      +13     
- Partials       5134     5146      +12     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@trustin trustin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

`

endpointPath?: string,
queries?: string,
): Promise<string> {
): Promise<{ body: string; headers: Record<string, string> }> {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should return ResponseData to preserve the header ordering and support multi-value headers. By doing so, we can remove extractHeaders below as well.

@hyunw9 hyunw9 Apr 14, 2025

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your review ! Belows are the changes :

  1. Introduced ResponseData to handle response (body + headers).
  2. Implemented multi-value headers handling using Map<string, string[]>.
  3. Updated header display logic in DebugPage to follow RFC9110 §5.2 guidelines.

RFC9110 specifies:

"A sender MUST NOT generate multiple header fields with the same field name unless the entire field value is comma-separated or the field explicitly allows multiple field lines."

Thus, I defined ResponseData in types.tsx as:

https://github.com/hyunw9/armeria/blob/9705ab2a375c66f0f383edfd526249c5f7f6c150/docs-client/src/lib/types.ts#L28-L31

Replaced Response with <ResponseData> in abstract doSend<Response>, and aggregated response headers:

https://github.com/hyunw9/armeria/blob/9705ab2a375c66f0f383edfd526249c5f7f6c150/docs-client/src/lib/transports/annotated-http.ts#L126-L133

Adjusted DebugPage header display:

https://github.com/hyunw9/armeria/blob/9705ab2a375c66f0f383edfd526249c5f7f6c150/docs-client/src/containers/MethodPage/DebugPage.tsx#L664-L672

When server set headers like this :

final HttpHeaders headers = HttpHeaders.builder()
                                         .add("x-role", "admin")
                                         .add("x-role", "editor")
                                         .add("x-role", "user")
                                         .build();

Now, multi-value headers appear correctly as below:

Response Headers

If you have any feedback or suggestions, I’d really appreciate your comments!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! It looks much better. However, I'd like you to consider the following:

  • The RFC you mentioned doesn't prohibit specifying multiple header values with the same header name if the multiple field lines are allowed explicitly.
  • At the protocol level, these two are different:
    x-role: admin, editor, user
    
    vs.
    x-role: admin
    x-role: editor
    x-role: user
    

Therefore, what do you think about using plaintext rather than JSON to render the response headers?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please also note that the following are considered different, although they are semantically same:

x-role: admin
other-header: other value
x-role: user

vs.

x-role: admin
x-role: user
other-header: other value

.. which means we need to preserve the ordering, which cannot be achieved by using a Map.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initially, I didn’t consider the preservation of header order or merging rules.
However, after reviewing RFC 9110, I found that only headers defined using the #element syntax are safe to merge using commas.
For other headers, merging can result in loss of semantics or parsing errors.

For example, the Date header value like "Sat, 19 Apr 2025 09:00:00 GMT" includes a comma as part of the value.
Blindly splitting on commas would incorrectly produce lines like:

date: Sat
date: 19 Apr 2025 09:00:00 GMT

Initially, I implemented naive comma-splitting across all headers.
After identifying this issue, I refined the logic to selectively split only list-type headers, while preserving others unchanged.

The updated logic iterates through the response Headers object:

  1. If a header is recognized as a list-type (e.g., Accept, Cache-Control), it splits the value by comma and renders each entry individually.

  2. Otherwise, it preserves the header as a single line to avoid unintended splitting.

Example

Comment thread docs-client/src/lib/transports/grahpql-http.ts Outdated
Comment thread docs-client/src/containers/MethodPage/DebugPage.tsx Outdated
Comment thread docs-client/src/containers/MethodPage/DebugPage.tsx Outdated
Comment thread docs-client/src/containers/MethodPage/DebugPage.tsx Outdated
Comment thread docs-client/src/containers/MethodPage/DebugPage.tsx
@ikhoon ikhoon added this to the 1.33.0 milestone Apr 17, 2025
Comment thread docs-client/src/containers/MethodPage/DebugPage.tsx Outdated
Comment on lines +428 to +432
setResponseCache((prev) => ({
...prev,
[currentApiId]: {
body,
headers: responseHeaders,

@ikhoon ikhoon Apr 22, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be more useful if we could record the execution time and display it in the debug console. Some may want to know whether the response is outdated or up-to-date.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think showing the execution time on the debug page could improve the user experience!

If we decide to display it, where would be the best place to show the execution time?
I was thinking of showing it in a separate section, similar to other API testing tools.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It sounds good to me. Could you prototype your idea? I’d like to see how it looks and feels.

@hyunw9 hyunw9 Apr 23, 2025

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In modern API Testing tools, they display Response status, execution time, and ResponseData size.

So i was thinking what if we displayed those three information on the right section of response page Util.

Examples :

Postman Bruno

Prototype :

ResponsePage DebugConsole

More specifically, I thought of two possible versions :

Text-like Colored

--- Updated ---
I put together a quick prototype implementation. Let me know what you think !

Fail Success

Executed time should be rounded tho :)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The prototype looks great! Since the results are cached, would you mind also adding the timestamp of when the request was executed?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure! It’s necessary when we’re caching ResponseData.
I’ve just added the update :)

  1. As previously discussed, the cache now stores the entire ResponseData object instead of selected values.
  2. Updated the DebugPage to display the newly added fields from ResponseData. The logic for determining colors is as follows: Diff

Here are some examples pictures:

2xx 4xx Invalid

Comment thread docs-client/src/containers/MethodPage/DebugPage.tsx Outdated
Comment thread docs-client/src/lib/json-util.ts
Comment thread docs-client/src/containers/MethodPage/DebugPage.tsx

@ikhoon ikhoon left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, @hyunw9 👍 👍

@ikhoon
ikhoon merged commit f433882 into line:main Jun 23, 2025
ikhoon added a commit to ikhoon/armeria that referenced this pull request Oct 10, 2025
Motivation:

JSON pretty-printing logic was unintentionally removed while working on line#6191
https://github.com/line/armeria/pull/6191/files#diff-f12e66c572a486106958b3f165d995f093e16ffb76db3028fd836595eace6c67L64-L67

Modifications:

- Prettify JSON responses before rendering them on the debug console.
- Remove duplicate duration measurement logic.
- Slightly adjust the font size and layout spacing in
  `ResponseStatusBar` for readability.

Result:

Fix a regression where JSON responses are not formatted in DocService
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants